package cpm.itwn.springcloud;

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;

/**
 * Hystrix(熔断器)
 *      1.服务降级
 *      2.服务熔断
 *      3.服务限流
 *
 *
 ********** 1.服务降级
 *
 *      模拟一下错误:
 *程序运行异常        (运行时异常,超时异常,宕机)
 * 1.超时
 * 2.哪些情况会出发降级
 * 3.服务熔断触发服务降级
 * 4.线程池/信号量打满也会导致服务
 *
 *     场景模拟:
 *     20000线程访问    ,会把所有线程的访问速度变慢
 *
 *  1.问题每个方法都有一个兜底方法配置,导致代码膨胀
 *      @DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
 *      @HystrixCommand     //默认全局的兜底方法
 *      //自定义兜底方法
 *      @HystrixCommand(fallbackMethod = "paymentInfo_ConsumerTimeOutHandler",commandProperties = {
 *            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="6000")
 *     })
 *
 *  2.和业务代码混在一起,
 *  在创建一个service的实现类
 *  value表示可以调用这个微服务的全部方法
 *  fallback服务降级时要找的类
 *  @FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT",fallback = PaymentFallbackService.class)
 *
 *
 *
 **********     2.服务熔断
 *
 *
 *  熔断打开    请求不再进行调用当前服务，内部设置时钟一般为MTTR (平均故障处理时间)，当打开时长达到所设时钟则进入半熔断状态
 * 熔断关闭     熔断关闭不会对服务进行熔断
 * 熔断半开     部分请求根据规则调用当前服务，如果请求成功且符合规则则认为当前服务恢复正常，关闭熔断
 *
 *断路器开启或者关闭的条件:
 *      当满足一定的阀值的时候(默认10秒内超过20个请求次数)
 *      当失败率达到一定的时候( 默认10秒内超过50%的请求失败)
 *      到达以上阀值，断路器将会开启
 *      当开启的时候，所有请求都不会进行转发
 *      一段时间之后 (默认是5秒)，这个时候断路器是半开状态，会让其中一个请求进行转发。
 *      如果成功，断路器会关闭，若失败,继续开启。重复4和5
 */


@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker   //Hystrix 有关    回路
public class PaymentHystrixMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentHystrixMain8001.class,args);
    }



    /**
     *此配置是为了服务监控而配置，与服务 容错本身无关，springcloud 升级后的坑
     *ServletRegistrationBean因为springboot的默认路径不是"/hystrix. stream",
     *只要在自己的项目里配置上下面的servlet就可以了
     */
    @Bean
    public ServletRegistrationBean getServlet() {
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }
}
